package com.zzedu.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.zzedu.common.core.domain.entity.SysDept;
import com.zzedu.common.core.domain.entity.SysRole;
import com.zzedu.common.enums.CommonEnums;
import com.zzedu.common.utils.StringUtils;
import com.zzedu.system.mapper.SysDeptMapper;
import com.zzedu.system.service.ISysDeptService;
import com.zzedu.system.service.ISysRoleService;
import com.zzedu.system.vo.TreeSelect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 部门管理 服务实现
 *
 * @author smarthome
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {
    @Autowired
    ISysRoleService sysRoleService;

    @Override
    public IPage<SysDept> selectDeptList(IPage<SysDept> page, SysDept dept) {
        LambdaQueryWrapper<SysDept> queryWrapper = Wrappers.lambdaQuery(SysDept.class);
        queryWrapper.eq(null != dept.getId(), SysDept::getId, dept.getId());
        queryWrapper.eq(null != dept.getParentId(), SysDept::getParentId, dept.getParentId());
        queryWrapper.like(StringUtils.isNotBlank(dept.getDeptName()), SysDept::getDeptName, dept.getDeptName());
        queryWrapper.eq(StringUtils.isNotBlank(dept.getStatus()), SysDept::getStatus, dept.getStatus());
        queryWrapper.orderByAsc(SysDept::getParentId, SysDept::getOrderNum);
        return this.page(page, queryWrapper);
    }

    public List<TreeSelect> selectDeptTreeList(SysDept dept) {
        LambdaQueryWrapper<SysDept> queryWrapper = Wrappers.lambdaQuery(SysDept.class);
        queryWrapper.eq(null != dept.getId(), SysDept::getId, dept.getId());
        queryWrapper.eq(null != dept.getParentId(), SysDept::getParentId, dept.getParentId());
        queryWrapper.like(StringUtils.isNotBlank(dept.getDeptName()), SysDept::getDeptName, dept.getDeptName());
        queryWrapper.eq(StringUtils.isNotBlank(dept.getStatus()), SysDept::getStatus, dept.getStatus());
        queryWrapper.orderByAsc(SysDept::getParentId, SysDept::getOrderNum);
        List<SysDept> depts = this.list(queryWrapper);
        return buildDeptTreeSelect(depts);
    }


    /**
     * 构建前端所需要下拉树结构
     *
     * @param depts 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts) {
        List<SysDept> deptTrees = buildDeptTree(depts);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 根据角色ID查询部门树信息
     *
     * @param roleId 角色ID
     * @return 选中部门列表
     */
    public List<Long> selectDeptListByRoleId(Long roleId) {
        SysRole role = sysRoleService.selectRoleById(roleId);
        LambdaQueryWrapper<SysDept> queryWrapper = Wrappers.lambdaQuery(SysDept.class);
        queryWrapper.apply("id in(select dept_id from sys_role_dept where deleted=0 and role_id={0})", role.getId());
        if (role.isDeptCheckStrictly()) {
            queryWrapper.apply("id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.id = rd.dept_id and rd.role_id = {0})", role.getId());
        }
        queryWrapper.orderByAsc(SysDept::getParentId, SysDept::getOrderNum);
        List<SysDept> sysDeptList = this.list(queryWrapper);
        return Optional.ofNullable(sysDeptList).orElse(Lists.newArrayList()).stream().map(SysDept::getId).collect(Collectors.toList());
    }

    @Override
    public SysDept selectDeptById(Long deptId) {
        return getById(deptId);
    }

    /**
     * 根据ID查询所有子部门（正常状态）
     *
     * @param deptId 部门ID
     * @return 子部门数
     */
    public long selectNormalChildrenDeptById(Long deptId) {
        LambdaQueryWrapper<SysDept> queryWrapper = Wrappers.lambdaQuery(SysDept.class);
        queryWrapper.eq(SysDept::getStatus, String.valueOf(CommonEnums.YES.getCode()));
        queryWrapper.eq(SysDept::getParentId, deptId);
        return count(queryWrapper);
    }

    /**
     * 是否存在部门子节点
     *
     * @param deptId 部门ID
     * @return 结果
     */
    public boolean hasChildByDeptId(Long deptId) {
        LambdaQueryWrapper<SysDept> queryWrapper = Wrappers.lambdaQuery(SysDept.class);
        queryWrapper.eq(SysDept::getParentId, deptId);
        return count(queryWrapper) > 0;
    }

    /**
     * 查询部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    public boolean checkDeptExistUser(Long deptId) {
        LambdaQueryWrapper<SysDept> queryWrapper = Wrappers.lambdaQuery(SysDept.class);
        queryWrapper.apply("id in(select dept_id from sys_user where deleted=0 and dept_id={0})", deptId);
        return count(queryWrapper) > 0;
    }

    /**
     * 构建前端所需要树结构
     *
     * @param depts 部门列表
     * @return 树结构列表
     */
    @Override
    public List<SysDept> buildDeptTree(List<SysDept> depts) {
        List<SysDept> returnList = new ArrayList<SysDept>();
        List<Long> tempList = depts.stream().map(SysDept::getId).collect(Collectors.toList());
        for (SysDept dept : depts) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = depts;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysDept> list, SysDept t) {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDept tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysDept> getChildList(List<SysDept> list, SysDept t) {
        List<SysDept> tlist = new ArrayList<SysDept>();
        Iterator<SysDept> it = list.iterator();
        while (it.hasNext()) {
            SysDept n = (SysDept) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDept> list, SysDept t) {
        return getChildList(list, t).size() > 0;
    }
}
